{-# OPTIONS_GHC -Wall -Werror -fno-warn-orphans #-}
{-# LANGUAGE FlexibleContexts, TypeFamilies, 
  FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances #-}

module Vector2D where

import Data.VectorSpace hiding (Scalar)
import qualified Data.VectorSpace as VS

import Math
import Projectable
import Control.Parallel.Strategies

data Vector2 = V2 !Scalar !Scalar deriving Eq

instance Show Vector2 where
  show (V2 x y) = "("++showN x++","++showN y++")"

type Direction2    = Vector2
type Offset2       = Vector2
type Scaling2      = Vector2
type Velocity2     = Vector2
type Acceleration2 = Vector2

-- | Construct a 2D vector
vector2 :: Scalar -> Scalar -> Vector2
vector2 = V2

polar :: Angle -> Length -> Vector2
polar radians radius = radius *^ vector2 (cos radians) (sin radians) 

getAngle :: Vector2 -> Scalar
getAngle (V2 x y) = atan2 y x

{-# INLINE vector2 #-} 

instance Project2 Vector2 where
  project2 (V2 x y) = (x,y)
  compose2 (x,y) = (V2 x y)

instance ProjectX Vector2 where
  getX (V2 x _) = x
  mapX f (V2 x y) = V2 (f x) y

instance ProjectY Vector2 where
  getY (V2 _ y) = y
  mapY f (V2 x y) = V2 x (f y)

instance AdditiveGroup Vector2 where
  zeroV = V2 0 0
  V2 x1 y1 ^+^ V2 x2 y2 = V2 (x1+x2) (y1+y2)
  negateV (V2 x y) = V2 (negate x) (negate y)

instance VectorSpace Vector2 where
  type VS.Scalar (Vector2) = Scalar
  s *^ V2 x y = V2 (s*x) (s*y)

instance InnerSpace Vector2 where
  V2 x1 y1 <.> V2 x2 y2 = x1*x2+y1*y2

instance NFData (Vector2)


 
